﻿using InternetSpiderLib.Scenes;
using InternetSpiderLib.Scenes.Actions;
using InternetSpiderLib.Scenes.DataSavers;
using InternetSpiderLib.Scenes.Filters;
using InternetSpiderLib.Scenes.UrlClassifications;
using InternetSpiderLib.Scenes.UrlHistories;
using InternetSpiderLib.Scenes.UrlQueues;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace InternetSpiderLib
{
    /// <summary>
    /// 场景的实际对象
    /// </summary>
    public class SceneItem
    {
        /// <summary>
        /// 场景排序依据
        /// </summary>
        public int SceneOrder { get; set; }

        /// <summary>
        /// 场景过滤器
        /// </summary>
        public ISceneFilter Filter { get; set; }

        /// <summary>
        /// 场景动作
        /// </summary>
        public ISceneAction SceneAction { get; set; }

        /// <summary>
        /// 链接分类器
        /// </summary>
        public IUrlClassification UrlClassification { get; set; }

        /// <summary>
        /// 网络链接
        /// </summary>
        public IUrlQueue UrlQueue { get; set; }

        /// <summary>
        /// 网络历史
        /// </summary>
        public IUrlHistories UrlHistories { get; set; }

        /// <summary>
        /// 数据存储器
        /// </summary>
        public IDataSaver DataSaver { get; set; }

        /// <summary>
        /// 运行这个场景
        /// </summary>
        /// <param name="data"></param>
        /// <returns></returns>
        public bool Run(DataBox data)
        {
            if (!(Filter?.Filter(new DataBox(data)) ?? true))
                return false;

            SceneContext context = new SceneContext
            {
                Context = data
            };

            SceneAction?.Run(context);

            // 保存结果数据
            DataSaver?.Save(context?.Result);

            // 保存Url数据
            if (UrlClassification != null)
            {
                if (context.Uris != null && context.Uris.Any())
                {
                    foreach (var uri in context.Uris)
                    {
                        var url = uri.AbsoluteUri;
                        var classInfo = UrlClassification.ClassificationInfoUrl(url);
                        if (classInfo == null)
                            continue;

                        if (classInfo.ClassificationType == UrlClassificationType.None)
                            continue;

                        if (UrlHistories != null)
                        {
                            if (UrlHistories.Exist(url) == false)
                            {
                                UrlHistories.AddHistory(url);

                                if (UrlQueue != null)
                                {
                                    UrlQueue.AddUrl(url, DateTime.Now);
                                }
                            }
                        }
                    }
                }
            }

            // 让这条Url后退
            var currentUrl = data?.Get<string>(SceneContextKey.Url);
            if (string.IsNullOrEmpty(currentUrl) == false)
            {
                if (UrlClassification != null)
                {
                    var classInfo = UrlClassification.ClassificationInfoUrl(currentUrl);
                    if (classInfo != null && classInfo.ClassificationType == UrlClassificationType.Retry)
                    {
                        if (UrlQueue != null)
                        {
                            UrlQueue.AddUrl(currentUrl, DateTime.Now.AddSeconds(classInfo.IntervalSecond));
                        }
                    }
                }
            }

            return true;
        }
    }
}
